<?php

// +----------------------------------------------------------------------
// | 大模型基础类(其他大模型应继承此类)基础类默认使用GLM-4-Flash大模型（免费）
// +---------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://www.redfox.com All rights reserved.
// +---------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +---------------------------------------------------------------------
// | Author: RedFox <<591006133@qq.com>>

require_once 'util/http.php';

/**
 * 大模型基础类
 * usage：
 * $config = ['token' => 'xxxxxxxx'];
 * $client = Zhipu::instance($config);
 * $result = $client->rewrite('hello world!', '请改写以下文本内容：', 0.7, 2048);
 */
class Zhipu
{

    private static $instance;

    //继承的子类应重写以下属性
    protected $big_model_name = 'GLM-4-Flash';
    protected $api = 'https://open.bigmodel.cn/api/paas/v4/chat/completions';
    protected $token = '';//test key

    public function __construct($config)
    {
        !empty($config['token']) && $this->token = $config['token'];
    }

    /**
     * 单例
     * @param array $options 参数
     * @return BigModelBase
     */
    public static function instance($options = [])
    {
        if (is_null(self::$instance)) {
            self::$instance = new static($options);
        }

        return self::$instance;
    }

    /**
     * 改写内容(继承类请重写此方法)
     * @param string $text 改写文本
     * @param string $prompt 改写指令
	 * @param float $prompt 温度值0.1-1
	 * @param int $prompt 最大消耗tokens
     * @return array
     */
    public function rewrite($text = '', $prompt = '请改写以下文本内容：', $temperature = 0.7, $max_tokens = 2048)
    {
        //构造请求参数
        // (智谱API接口使用chatglm4-falsh)
        $data = [
            "model" => "glm-4-flash", // 使用的模型
            "messages" => [
                [
                    "role" => "user",
                    "content" => $prompt . "\n" . $text
                ]
            ],
            "temperature" => $temperature, // 控制生成文本的随机性
            "max_tokens" => $max_tokens // 最大生成 token 数
        ];

        $headers = array(
            'request-time' => time(),
            'Authorization' => 'Bearer '. $this->token,
            'Content-Type' => 'application/json',
        );

        $result = $this->curlRequest('POST', $headers, $data, 60);

        if ($result['success']) {
            return $result['text'];
        }

        throw new \Exception($result['msg']);
    }

    //curl request请求大模型(仅支持post body为json类型请求)
    protected function curlRequest($method = 'POST', $headers = array(), $data = array(), $timeout = 60)
    {
        $result = array('success' => false, 'text' => '', 'msg' => '[error]');

        try {

            $header = [];
            foreach ($headers as $key => $value) {
                $header[] = $key . ': '. $value;
            }

            $options = [
                CURLOPT_HTTPHEADER => $header,
                CURLOPT_CONNECTTIMEOUT => 120,
                CURLOPT_TIMEOUT => 120,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_SSL_VERIFYPEER => false,
                CURLOPT_SSL_VERIFYHOST => false,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
            ];

            $response = Http::sendRequest($this->api, json_encode($data, JSON_UNESCAPED_UNICODE), $method, $options);

            if ($response['ret']) {

                $res = (array)json_decode($response['msg'], TRUE);

                if(isset($res['choices'][0]['message']['content'])){
                    $result = array('success' => true, 'text' => $res['choices'][0]['message']['content'], 'msg' => 'request success');
                    return $result;
                }

                if(isset($res['error']) && isset($res['error']['message']) && isset($res['error']['code'])) {
                    throw new \Exception("api error，code: " . $res['error']['code'] . " msg: " . $res['error']['message']);
                }

                throw new \Exception("result error， " . json_encode($res, JSON_UNESCAPED_UNICODE));
            }

            throw new \Exception("request error，" . $response['msg'] . $response['errno']);

        } catch (\Exception $e) {
            $result['msg'] = '[error] ' . $e->getMessage();
            return $result;
        }
    }


}
